package com.kreedx.kdemo.module.presenter;

import android.support.annotation.NonNull;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.kreedx.kdemo.module.contract.SocketContract;
import com.kreedx.kdemo.module.model.SocketModel;
import com.kreedx.kdemo.util.ByteArrayUtils;
import com.vilyever.socketclient.SocketClient;
import com.vilyever.socketclient.helper.SocketClientDelegate;
import com.vilyever.socketclient.helper.SocketPacketHelper;
import com.vilyever.socketclient.helper.SocketResponsePacket;
import com.vilyever.socketclient.util.CharsetUtil;

import io.xujiaji.xmvp.presenters.XBasePresenter;

public class SocketPresenter extends XBasePresenter<SocketContract.View,SocketModel> implements SocketContract.Presenter {
    private SocketClient socketClient;

    public SocketPresenter() {

    }


    @Override
    public void init() {
        view.upateState(SocketContract.Model.State.Disconnected);

        initSocket();
    }

    private void initSocket() {
        socketClient = new SocketClient();
        socketClient.getAddress().setRemoteIP("192.168.2.101");
        socketClient.getAddress().setRemotePort("9527");

        socketClient.setCharsetName(CharsetUtil.UTF_8);



        /**
         * 设置读取策略为自动读取指定长度
         */
        socketClient.getSocketPacketHelper().setReadStrategy(SocketPacketHelper.ReadStrategy.AutoReadByLength);
        /**
         * 设置包长度转换器
         * 即每次接收数据时，将远程端发送到本地的长度信息byte[]转换为int，然后读取相应长度的值
         *
         * 例：自动接收远程端所发送的socketClient.sendData(new byte[]{0x01, 0x02})【{0x01, 0x02}为将要接收的数据】的步骤为
         * 1. socketClient接收包头（如果设置了包头信息）（接收方式为一直读取到与包头相同的byte[],即可能过滤掉包头前的多余信息）
         * 2. socketClient接收长度为{@link SocketPacketHelper#getReceivePacketLengthDataLength()}（此处设置为4）的byte[]，通过下面设置的转换器，将byte[]转换为int值，此int值暂时称为X
         * 3. socketClient接收长度为X的byte[]
         * 4. socketClient接收包尾（如果设置了包尾信息）（接收方式为一直读取到与包尾相同的byte[],如无意外情况，此处不会读取到多余的信息）
         * 5. socketClient回调数据包
         *
         * 此转换器用于第二步
         *
         * 使用{@link com.vilyever.socketclient.helper.SocketPacketHelper.ReadStrategy.AutoReadByLength}必须设置此项
         * 用于分隔多条消息
         */
        socketClient.getSocketPacketHelper().setReceivePacketLengthDataLength(2);
        socketClient.getSocketPacketHelper().setReceivePacketDataLengthConvertor(new SocketPacketHelper.ReceivePacketDataLengthConvertor() {
            @Override
            public int obtainReceivePacketDataLength(SocketPacketHelper helper, byte[] packetLengthData) {
                /**
                 * 简单将byte[]转换为int
                 */
                int length = (packetLengthData[1] & 0xFF) | ((packetLengthData[0] & 0xFF) << 8);

                return length;
            }
        });


        socketClient.registerSocketClientDelegate(new SocketClientDelegate() {
            @Override
            public void onConnected(SocketClient client) {
                client.sendData("________socket_________".getBytes());

                if (view !=null){
                    view.upateState(SocketContract.Model.State.Connected);
                }

            }

            @Override
            public void onDisconnected(SocketClient client) {
               if (view !=null){
                   view.upateState(SocketContract.Model.State.Disconnected);
               }
            }

            @Override
            public void onResponse(SocketClient client, @NonNull SocketResponsePacket responsePacket) {
                String resp = responsePacket.getMessage();
                byte code[] = responsePacket.getData();
                String msg = resp.substring(4,resp.length());
                Log.i("msg", String.format("%d %s",ByteArrayUtils.toInt(code),msg));

                if (view != null){
                    view.onMessage(ByteArrayUtils.toInt(code),msg);
                }

            }
        });
    }

    @Override
    public void connect() {
        view.upateState(SocketContract.Model.State.Connecting);
        socketClient.connect();

    }

    @Override
    public void disconnect() {
        socketClient.disconnect();
    }

    @Override
    public void sendMessage(int opcode, Object object) {
        byte[] body = JSON.toJSONString(object).getBytes();
        byte[] head = ByteArrayUtils.toByteArray((short) (body.length + 4));
        byte[] code = ByteArrayUtils.toByteArray(opcode);

        byte[] msg = new byte[body.length + head.length + code.length];


        System.arraycopy(head, 0, msg, 0, head.length);
        System.arraycopy(code, 0, msg, head.length, code.length);
        System.arraycopy(body, 0, msg, head.length + code.length, body.length);

        socketClient.sendData(msg);
    }
}
